//
//  UpdateOperation.m
//  iChangeChecker
//
//  Created by Lauri Koskela on 20.4.2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "UpdateOperation.h"
#import "iChangeCheckerAppDelegate.h"
#import "UpdatedPageMenuItem.h"
#import <CommonCrypto/CommonDigest.h>

@implementation UpdateOperation

@synthesize delegate;

- (id)initWithDelegate:(ChangeCheckerAppDelegate*)newDelegate
{
    self = [super init];
    if (self) {
        self.delegate = newDelegate;
    }
    
    return self;
}

- (void)main {
    @try {
        NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
        [context setPersistentStoreCoordinator:[delegate persistentStoreCoordinator]];
        [context setMergePolicy:NSOverwriteMergePolicy];
        
        // Register context with the notification center
        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
        [nc addObserver:self
               selector:@selector(mergeChanges:)
                   name:NSManagedObjectContextDidSaveNotification
                 object:context];
        
        NSArrayController *siteArrayController = [[NSArrayController alloc] init];
        [siteArrayController setManagedObjectContext:context];
        [siteArrayController setEntityName:@"Page"];
        [siteArrayController fetchWithRequest:nil merge:YES error:NULL];
        
        if ([[siteArrayController arrangedObjects] count] == 0) {
            return;
        }
        
        BOOL anythingUpdated = NO;
        
        NSArray *pagesArray = [siteArrayController arrangedObjects]; 
        
        for (int i = 0; i < [pagesArray count]; i++) {
            if ([[pagesArray[i] valueForKey:@"updatedStatus"] isEqualToNumber:@YES]) continue;     // If the pages update status is already true, don't check again
            NSError *error;
            NSString *newString = [NSString stringWithContentsOfURL:[NSURL URLWithString:[pagesArray[i] valueForKey:@"address"]] encoding:NSUnicodeStringEncoding error:&error];
            if (newString == nil) {
                NSLog(@"%@", error);
                continue;
            }
            char* cString = (char*)[newString cStringUsingEncoding:NSUnicodeStringEncoding];
            unsigned char result[16];
            
            CC_MD5(cString, (CC_LONG)strlen(cString), result);
            NSString *newMD5 = [NSString stringWithFormat:
                                @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
                                result[0], result[1], result[2], result[3], 
                                result[4], result[5], result[6], result[7],
                                result[8], result[9], result[10], result[11],
                                result[12], result[13], result[14], result[15]];
            NSString *oldMD5 = [pagesArray[i] valueForKey:@"oldMD5"];
            
            if ([newMD5 isEqualToString:oldMD5]) {
                continue;
            } else {
                anythingUpdated = YES;
                if ([[delegate statusMenu] indexOfItem:[delegate updatedLabel]] == -1) {
                    [[delegate statusMenu] insertItem:[delegate updatedLabel] atIndex:[[delegate statusMenu] indexOfItemWithTag:5]];
                    [[delegate statusMenu] insertItem:[delegate separator] atIndex:[[delegate statusMenu] indexOfItemWithTag:5]];
                }
                
                if ([pagesArray[i] valueForKey:@"name"] == nil) {
                    [pagesArray[i] setValue:[pagesArray[i] valueForKey:@"address"] forKey:@"name"];
                }
                
                UpdatedPageMenuItem *item = [[UpdatedPageMenuItem alloc] initWithTitle:(NSString*)[pagesArray[i] valueForKey:@"name"] action:@selector(openPage:) keyEquivalent:@""];
                [item setTarget:delegate];
                [item setAddress:[pagesArray[i] valueForKey:@"address"]];
                [item setID:[pagesArray[i] valueForKey:@"ID"]];
                [item setDelegate:delegate];
                [[delegate statusMenu] insertItem:item atIndex:[[delegate statusMenu] indexOfItem:[delegate separator]]];
                
                [delegate sendTwitterNotificationWithName:[pagesArray[i] valueForKey:@"name"] link:[pagesArray[i] valueForKey:@"address"]];
                
                [[siteArrayController arrangedObjects][i] setValue:@YES forKey:@"updatedStatus"];
                [[siteArrayController arrangedObjects][i] setValue:newMD5 forKey:@"oldMD5"];
            }
        }
        
        if (anythingUpdated) {
            [[NSSound soundNamed:@"Glass"] play];
            NSString *iconPath = [[NSBundle mainBundle] pathForResource:@"updatedMenuIcon" ofType:@"png"];
            NSImage *statusIcon = [[NSImage alloc] initWithContentsOfFile:iconPath];
            [statusIcon setSize:NSMakeSize(25.0, 15.0)];
            [delegate.statusItem setImage:statusIcon];
        }
        
        NSError *error;
        [context save:&error];
        
        NSString *currentTime = [NSDateFormatter localizedStringFromDate:[NSDate date]
                                                               dateStyle:NSDateFormatterNoStyle 
                                                               timeStyle:NSDateFormatterShortStyle];
        NSString *title = [NSString stringWithFormat:@"Last Updated: %@", currentTime];
        [delegate.statusMenu cancelTracking];
        [delegate.lastUpdatedItem setTitle:title];
    }
    @catch (NSException *exception) {
        NSLog(@"exception: %@", exception);
    }
}

- (void)mergeChanges:(NSNotification *)notification
{
    NSManagedObjectContext *mainContext = [delegate managedObjectContext];
    // Merge changes into the main context on the main thread
    [mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                                  withObject:notification
                               waitUntilDone:YES]; 
}


@end
